﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Statistics;
using NHibernate;
using NHibernate.Criterion;
using Attribute = ControleRepresentante.Logic.Models.Attribute;

namespace ControleRepresentante.Logic.Repositories
{
    public interface IAttributeRepository : IRepository<Attribute, StatisticsBase>
    {
        IEnumerable<Attribute> GetAttributesByType(AttributeType attributeType);
    }

    public class AttributeRepository : GeneralRepositoryBase<Attribute, StatisticsBase, AttributeError>, IAttributeRepository
    {
        public AttributeRepository(IRepositoryConfiguration repositoryConfiguration, ISession session) 
            : base(repositoryConfiguration, session)
        {
        }

        protected override StatisticsBase GetStatistics(int modelCount)
        {
            return new StatisticsBase(modelCount);
        }

        protected override void OnBeforeRemove(Attribute model)
        {
            model.ClearAttributeValues();
        }

        protected override IQueryOver<Attribute, Attribute> GetModelsQueryOver()
        {
            return Session.QueryOver<Attribute>()
                .Where(x => x.Representante.Id == GetRepresentanteId())
                .OrderBy(x => x.Name).Asc;
        }

        protected override IEnumerable<Expression<Func<Attribute, bool>>> GetUniquenessExpressions(Attribute model)
        {
            yield return x => x.Representante.Id == GetRepresentanteId();
            yield return x => x.Name == model.Name;
            yield return x => x.Type == model.Type;
        }

        protected override IQueryOver<Attribute, Attribute> GetModelByIdQueryOver(IQueryOver<Attribute, Attribute> queryOver, Guid id)
        {
            return queryOver.And(x => x.Representante.Id == GetRepresentanteId());
        }

        protected override AttributeError DuplicatedError { get { return AttributeError.DuplicatedName; } }

        public IEnumerable<Attribute> GetAttributesByType(AttributeType attributeType)
        {
            return Session.QueryOver<Attribute>()
                .Where(x => x.Representante.Id == GetRepresentanteId())
                .And(x => x.Type == attributeType)
                .Future();
        }

        public override IEnumerable<Attribute> GetModelsByIds(IEnumerable<Guid> ids)
        {
            return Session.QueryOver<Attribute>()
                .Where(x => x.Representante.Id == GetRepresentanteId())
                .And(x => x.Id.IsIn(ids.ToArray()))
                .List();
        }
    }

    public enum AttributeError
    {
        DuplicatedName
    }
}
